package com.avo.ramcache.manager;

import com.avo.ramcache.config.CachedEntityConfig;
import com.avo.ramcache.config.IEntity;
import com.avo.ramcache.orm.Accessor;
import com.avo.ramcache.orm.Querier;
import com.avo.ramcache.persist.Persister;
import com.avo.ramcache.persist.PersisterConfig;
import com.avo.ramcache.persist.PersisterType;
import com.avo.ramcache.service.EntityCacheService;
import com.avo.ramcache.service.RegionCacheService;
import com.avo.ramcache.service.impl.EntityCacheServiceImpl;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

@SuppressWarnings({"rawtypes"})
public class CacheServiceManager {

    private final Accessor accessor;
    private final Querier querier;
    private final Map<String, PersisterConfig> persisterConfigs;
    private final Map<Class<? extends IEntity<?>>, CachedEntityConfig> entityConfigs = new HashMap<>();
    private final Map<String, Persister> persisters = new HashMap<>();
    private final Map<Class<? extends IEntity<?>>, EntityCacheService> entityCacheServices = new HashMap<>();
    private final Map<Class<? extends IEntity<?>>, RegionCacheService> regionCacheServices = new HashMap<>();

    public CacheServiceManager(Set<Class<IEntity<?>>> entityClasses, Accessor accessor, Querier querier,
                               Map<String, Integer> constants, Map<String, PersisterConfig> persisterConfigs) {
        this.accessor = accessor;
        this.querier = querier;
        this.persisterConfigs = persisterConfigs;
        for (Class<IEntity<?>> clz : entityClasses) {
            if (!CachedEntityConfig.isValid(clz, constants)) {
                throw new RuntimeException("无效的缓存实体" + clz.getName() + "配置");
            }
            CachedEntityConfig config = CachedEntityConfig.valueOf(clz, constants);
            this.entityConfigs.put(clz, config);
        }
    }

    public CachedEntityConfig getEntityConfig(Class<? extends IEntity<?>> clz) {
        return entityConfigs.get(clz);
    }

    public EntityCacheService getEntityService(Class<? extends IEntity<?>> clz) {
        return entityCacheServices.computeIfAbsent(clz, this::createEntityService);
    }

    public RegionCacheService getRegionService(Class<? extends IEntity<?>> clz) {
        return regionCacheServices.computeIfAbsent(clz, this::createRegionService);
    }

    private Persister getPersister(String name) {
        Persister persister = persisters.get(name);
        if (persister != null) {
            return persister;
        }
        if (!persisterConfigs.containsKey(name)) {
            throw new RuntimeException("持久化处理器 " + name + " 的配置信息不存在");
        }
        PersisterConfig config = persisterConfigs.get(name);
        PersisterType persisterType = config.getType();
        persister = persisterType.createPersister();
        persister.initialize(name, accessor, config.getValue());
        persisters.put(name, persister);
        return persister;
    }

    private EntityCacheService createEntityService(Class<? extends IEntity<?>> clz) {
        if (this.entityCacheServices.containsKey(clz)) {
            return this.entityCacheServices.get(clz);
        }
        CachedEntityConfig config = this.entityConfigs.get(clz);
        Persister persister = getPersister(config.getPersisterName());
        EntityCacheServiceImpl result = new EntityCacheServiceImpl();
        result.initialize(config, persister, this.accessor, this.querier);
        entityCacheServices.put(config.getClz(), result);
        return result;
    }

    private RegionCacheService createRegionService(Class<? extends IEntity<?>> clz) {
        throw new RuntimeException("没有实现RegionCacheService");
    }

    public void shutdown() {
        persisters.values().forEach(Persister::shutdown);
    }
}
